package com.tnovoselec.android.common.async.listener;

import java.util.concurrent.Future;


public abstract class Outcome<K, T> implements ResultListener<K, T> {

	/**
	 * {@inheritDoc}
	 * <p>
	 * This implementation handles a result by calling either {@link #succeeded} or {@link #failed}.
	 * </p>
	 */
	@Override
	public final void onResult(K key, Future<T> result) {
		finished(key);

		// Check if the computation was successful by trying to get the result.
		// get() throws an exception if something went wrong.
		try {
			succeeded(key, result.get());
		} catch (Throwable t) {
			failed(key, t);
		}
	}

	/**
	 * Called as soon as we know the computation has finished, regardless of
	 * whether it succeeded or failed. Override this method to perform an
	 * action which is always required to happen when the task finishes running.
	 * 
	 * @param key The key of the operation which has finished.
	 */
	protected void finished(K key) {
		/* Do nothing */
	}

	/**
	 * Called when the task finished executing successfully.
	 * 
	 * @param key The key identifying the task which finished.
	 * @param result The result of the task's execution.
	 */
	protected abstract void succeeded(K key, T result);

	/**
	 * Called when the task failed to execute normally.
	 * 
	 * @param key The key identifying the task which failed.
	 * @param t The <code>Throwable</code> which occurred, causing the task to fail.
	 */
	protected abstract void failed(K key, Throwable t);
}
